package net.csdn.business.mirror.scheduled.handler;

import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import net.csdn.business.mirror.entity.bean.ScheduleTask;
import net.csdn.business.mirror.enums.TaskType;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Date;
import java.util.Map;

/**
 * 动态任务5
 * 任务注册器
 * 提供执行, 提交任务的api, 实现 DisposableBean 接口, 便于在bean销毁时将任务一起销毁
 */
@Component
@Slf4j
public class TaskRegister implements DisposableBean {

    private final Map<String, TimedTask> taskMap = Maps.newConcurrentMap();

    @Resource
    @Qualifier("taskScheduler")
    private TaskScheduler scheduler;

    /**
     * 提交任务 一次性
     */
    public void submit(TaskType type, Date time, ScheduleTask scheduleTask) {
        // 获取任务
        TimedTask timedTask = this.getTask(type, scheduleTask);
        // 执行任务
        timedTask.submit(scheduler, time);
    }

    /**
     * 提交任务 cron表达式
     */
    public void submit(TaskType type, ScheduleTask scheduleTask) {
        log.info("生成新的任务，scheduleTask: {}", scheduleTask);
//        try {
//            Duration duration = TimeUtil.getCronDuration(scheduleTask.getCron());
//            if (duration.toMinutes() < 1) {
//                log.info("时间间隔最少1分钟");
//                return;
//            }
//        } catch (Exception e) {
//            log.error("任务配置错误，conf: {}", scheduleTask, e);
//            return;
//        }
        // 获取任务
        TimedTask timedTask = this.getTask(type, scheduleTask);
        // 执行任务
        timedTask.submit(scheduler, new CronTrigger(scheduleTask.getCron()));
    }

    /**
     * 获取任务
     */
    private TimedTask getTask(TaskType type, ScheduleTask scheduleTask) {
        // 生成任务
        Runnable runnable = type.create(scheduleTask);
        String key = type.getKey(scheduleTask);
        // 判断是否存在任务
        if (taskMap.containsKey(key)) {
            log.error("任务已存在，key: [{}]", key);
            throw new RuntimeException("任务已存在，key: " + key);
        }
        TimedTask timedTask = new TimedTask(runnable);
        taskMap.put(key, timedTask);
        return timedTask;
    }


    /**
     * 取消任务
     */
    public void cancel(TaskType type, ScheduleTask scheduleTask) {
        String key = type.getKey(scheduleTask);
        TimedTask task = taskMap.get(key);
        if (task != null) {
            taskMap.remove(key);
            task.cancel();
        }
    }

    /**
     * 是否存在
     */
    public boolean has(TaskType type, ScheduleTask scheduleTask) {
        return taskMap.containsKey(type.getKey(scheduleTask));
    }

    @Override
    public void destroy() {
        log.info("销毁所有任务");
        taskMap.values().forEach(TimedTask::cancel);
        taskMap.clear();
    }

}